# coding:utf-8
# Author: legend
# @Time： 2020/8/27 下午10:05
from itertools import groupby
from operator import itemgetter

from pyflux_influxdb.flux import FluxQ, FluxR
from tortoise.exceptions import DoesNotExist

from apps.resource.models import Service
from utils.influx_db import get_query_flux, get_number_flux


class BaseHandler:

    def __init__(self, channel_name, channel_group_name, route):
        self.channel_name = channel_name
        self.channel_group_name = channel_group_name
        self.route = route
        self.response_serializer_class, self.response_handler_class = self.route[2:]
        # self.channel_layer = get_channel_layer()

    async def do(self, *args, **kwargs):
        raise NotImplementedError()

    def get_response_serializer(self, **kwargs):
        s = self.response_serializer_class(data=kwargs)
        s.is_valid(raise_exception=True)
        return s

    async def get_monitor_data(self, data_type, target_id, measurement, limit_number, many=False):
        """
        从influxdb中获取统计信息
        :param many: 是否返回多个，比如分区，网卡这类的数据，有多个的时候为True
        :param data_type: 类型0为设备 其他为服务
        :param target_id: 设备或者服务id
        :param measurement: 表名
        :param limit_number: 数据条数
        :return:
        """
        if data_type == 0:
            if many:
                if limit_number == 1:
                    try:
                        time = \
                            await \
                            get_query_flux(measurement, [('device_id', str(target_id)), ], [], 1, 0, '_time', True,
                                           '-5m',
                                           None)[0].get('time')
                    except IndexError:
                        time = \
                            await \
                            get_query_flux(measurement, [('device_id', str(target_id)), ], [], 1, 0, '_time', True,
                                           '-1y',
                                           None)[0].get('time')
                    result = await get_query_flux(measurement, [('device_id', str(target_id)), ],
                                                  [FluxQ(getattr(FluxR(), 'time'), time)], 0, 0, '_time',
                                                  True, '-2y', None)
                    return list(reversed(result))
                else:

                    number = get_number_flux(measurement, 'device_id', str(target_id))
                    result_value = await get_query_flux(measurement, [('device_id', str(target_id)), ],
                                                        [],
                                                        limit_number * number, 0, '_time', True, f'-{limit_number}m',
                                                        None)
                    result = []
                    result_temp = []
                    for item in result_value:
                        if len(result_temp) == 0:
                            result_temp.append(item)
                        else:
                            if item.get('time') == result_temp[0].get('time'):
                                result_temp.append(item)
                            else:
                                result.append(list(reversed(result_temp)))
                                result_temp.clear()
                                result_temp.append(item)
                    return result
            else:
                return await get_query_flux(measurement, [('device_id', str(target_id)), ], [], limit_number, 0,
                                            '_time',
                                            True, '-2y', None)
        else:
            return await get_query_flux(measurement, [('service_id', str(target_id)), ], [], limit_number, 0, '_time',
                                        True, '-2y', None)

    async def query_process_status(self, limit_number, services):
        result_data = []
        tag_filter = []
        for service in services:
            tag_filter.append(('service_id', str(service)))
        origin_result = await get_query_flux("service.status", tag_filter, [], limit_number, 0, '_time', True, '-10h',
                                             None)
        origin_result.sort(key=itemgetter('time'))
        for time, result_item in groupby(origin_result, itemgetter('time')):
            temp_list = list(result_item)
            for temp in temp_list:
                try:
                    service = await Service.get(id=int(temp.get('service_id')))
                    temp.update({'service_id': int(temp.get('service_id')),
                                 'service': service.name})
                except DoesNotExist as e:
                    temp.update({'service_id': int(temp.get('service_id'))})
            result_data.append(sorted(temp_list, key=itemgetter('service_id')))
        return result_data
